#lang racket

(require "util/utils.scm")
(require "pass-tag.scm")
(require "pass-scope.scm")
(require "pass-letrec.scm")
(require "pass-hoist.scm")
(require "pass-denest.scm")
(require "pass-temps.scm")
;;(require "pass-mark-calls.scm")
(require "pass-flat.scm")
(require "pass-delabel.scm")
(require "pass-labels.scm")
(require "pass-csans.scm")
(require "opt-known-calls.scm")
(require "interpreter.scm")

(define args (vector->list (current-command-line-arguments)))

(define (pretty-print-assoc a)
  (for-each (lambda (entry)
              (print (car entry))
              (for-each pretty-print (cdr entry))
              (newline))
            a))


(cond ((= 1 (length args))
       (let ((command (string->symbol (car args))))
	 (unless (eq? command 'run)
	   (print "NO")(exit))
	 (run)))
      
      ((>= (length args) 2)
       (let ((command (string->symbol (car args)))
	     (source (apply append (map read-from-file (cdr args)))))
       
       (case command
	 ((help) (print "No help available"))
	 
	 ((tag) (for-each pretty-print (pass-tag source)))
	 ((scope) (for-each pretty-print (pass-scope (pass-tag source))))
	 ((letrec) (pretty-print-assoc (pass-letrec (pass-scope (pass-tag source)))))

	 ((hoist) (pretty-print-assoc (pass-hoist (pass-letrec (pass-scope (pass-tag source))))))
	 ((hoist+) (pretty-print-assoc (opt-known-calls (pass-hoist (pass-letrec (pass-scope (pass-tag source)))))))
	 
	 ((denest) (pretty-print-assoc (pass-denest (pass-hoist (pass-letrec (pass-scope (pass-tag source)))))))
	 ((temps) (pretty-print-assoc (pass-temps (pass-denest (pass-hoist (pass-letrec (pass-scope (pass-tag source))))))))
	 ;;((mark-calls) (pretty-print-assoc (pass-mark-calls (pass-denest (pass-hoist (pass-letrec (pass-scope (pass-tag source))))))))
	 ((flat) (pretty-print-assoc (pass-flat (pass-temps (pass-denest (pass-hoist (pass-letrec (pass-scope (pass-tag source)))))))))
	 ((delabel) (pretty-print-assoc (pass-delabel (pass-flat (pass-temps (pass-denest (pass-hoist (pass-letrec (pass-scope (pass-tag source))))))))))
	 
	 ((compile) (for-each pretty-print (pass-delabel (pass-flat (pass-temps (pass-denest (pass-hoist (pass-letrec (pass-scope (pass-tag source))))))))))
	 ((exec) (interp (pass-delabel (pass-flat (pass-temps (pass-denest (pass-hoist (pass-letrec (pass-scope (pass-tag source))))))))))
	 ((exec+) (interp (pass-delabel (pass-flat (pass-temps (pass-denest (opt-known-calls (pass-hoist (pass-letrec (pass-scope (pass-tag source)))))))))))

	 ((c) (pass-csans (pass-labels (pass-flat (pass-temps (pass-denest (pass-hoist (pass-letrec (pass-scope (pass-tag source)))))))) #f))
	 ((c+) (pass-csans (pass-labels (pass-flat (pass-temps (pass-denest (opt-known-calls (pass-hoist (pass-letrec (pass-scope (pass-tag source))))))))) #f))
	 
	 (else (print "Unknown command"))))
       
       )
      (else
       (error 'main "need two args")))
